package com.mrd.frame.onlinepay.pay.impl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.mrd.frame.controller.SweepPaymentAction;
import com.mrd.frame.domain.AccessConfig;
import com.mrd.frame.domain.Order;
import com.mrd.frame.domain.OrderInteraction;
import com.mrd.frame.domain.message.PayMessage;
import com.mrd.frame.domain.params.PayParams;
import com.mrd.frame.onlinepay.QrCreateBean;
import com.mrd.frame.onlinepay.pay.IPay;
import com.mrd.frame.service.OrderInteractionService;
import com.mrd.frame.service.OrderService;
import com.mrd.weixinpay.util.Constents;
import com.mrd.weixinpay.util.HttpUtil;
import com.mrd.weixinpay.util.PayCommonUtil;
import com.mrd.weixinpay.util.XMLUtil;

@Component("wxPlay")
public class WxPlay implements IPay{
	private static final Logger	logger	= Logger.getLogger(SweepPaymentAction.class);
	@Value("${pay.weixin.deployIpLochost}")
	private String	            deployIp;
	@Value("${pay.weixin.systemPublishPath}")
	private static String	    publishPath;
	@Value("${pay.weixin.notifyurlOriginal}")
	private String	            notifyurlOriginal;
	@Value("${pay.weixin.ufdoderUrlFormal}")
	private String	            ufdoderUrlFormal;
	@Autowired
	protected QrCreateBean	    arCreateBean;
	
	@Override
	public Map<String,Object> pay(AccessConfig accessConfig,PayParams payParams,Order order,OrderInteraction orderInt,
			PayMessage payMessage,OrderService	orderService,OrderInteractionService orderInteractionService) {
		Map<String, Object> retMap = new HashMap<String, Object>();
		String retresXML = "";
		String newRequest = "NO";

		// 向微信发起支付请求的参数
		String appid = accessConfig.getAppId();  // appid
		String mch_id = accessConfig.getMchId(); // 商业号
		String key = accessConfig.getPrivateKey(); // key
		// 随机数
		String currTime = PayCommonUtil.getCurrTime();
		String strTime = currTime.substring(8, currTime.length());
		String strRandom = PayCommonUtil.buildRandom(4) + "";
		String nonce_str = strTime + strRandom;
		// 获取发起支付请求的电脑 ip PayConfig.createIpLochost

		String spbill_create_ip = deployIp;
		// 回调接口 PayConfig.notifyurlOriginal
		String notify_url = notifyurlOriginal;
		String trade_type = "NATIVE";
		String body = payParams.getSubject();
		String out_trade_no = "";
		String order_price = payParams.getTotalAmount();

		// 将订单信息插入订单表中
		order.setOrderId(String.valueOf(System.currentTimeMillis()));
		order.setPayChannel("1");
		order.setStatus("1");
		order.setTradeNo(payParams.getOutTradeNo());
		order.setTimeStart(new Date());
		order.setTotalAmount(Integer.parseInt(order_price));
		order.setTradeType("1");
		order.setUserKey(payParams.getUserKey());
		order.setPayType(trade_type);

		Integer r1 = orderService.insert(order);

		// 将客户端请求支付端的信息存入交互记录表中
		orderInt.setOrderId(order.getOrderId());
		int a1 = orderInteractionService.insert(orderInt);

		out_trade_no = order.getOrderId();
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		packageParams.put("appid", appid);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		packageParams.put("out_trade_no", out_trade_no);
		packageParams.put("total_fee", order_price);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);
		packageParams.put("trade_type", trade_type);

		String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
		packageParams.put("sign", sign);


		String requestXML = PayCommonUtil.getRequestXml(packageParams);
		logger.info("微信支付请求发送的消息：" + requestXML);
		System.out.println("微信支付请求发送的消息：" + requestXML);
		// 向第三方的支付请求存入交互记录表中
		orderInt.setCreateTime(new Date());
		orderInt.setParameters(requestXML);
		orderInt.setOrderInteractionId(String.valueOf(System.currentTimeMillis()));
		orderInt.setType("A2");
		Integer a2 = orderInteractionService.insert(orderInt);

		String resXml = "";
		// 将微信支付返回的信息存入交互表中
		Map map;
		try {
			// PayConfig.ufdoderUrlFormal
			resXml = HttpUtil.postData(ufdoderUrlFormal, requestXML);
			map = XMLUtil.doXMLParse(resXml);
			String returnCode = (String) map.get("return_code");
			String resultCode = (String) map.get("result_code");
			if("SUCCESS".equals(resultCode) && "SUCCESS".equals(returnCode)) {
				orderInt.setStatus("0");
			} else {
				orderInt.setStatus("1");
			}
			orderInt.setCreateTime(new Date());
			orderInt.setParameters(requestXML);
			orderInt.setOrderInteractionId(String.valueOf(System.currentTimeMillis()));
			orderInt.setType("A3");
			Integer a3 = orderInteractionService.insert(orderInt);
			logger.info("微信支付请求返回的消息：" + resXml);
			System.out.println("微信支付请求返回的消息：" + resXml);
			retresXML = resXml;

			// 使用返回的url生成二维码
			String nonStr = order.getOrderId();
			String retMsg = "";
			String qrAddress = "";
			String codeUrl = "";
			if("SUCCESS".equals(resultCode) && "SUCCESS".equals(returnCode)) {
				codeUrl = (String) map.get("code_url");
				qrAddress = arCreateBean.saveQr(codeUrl, nonStr);
				// saveQr(codeUrl, nonStr);
				order.setQrUrl(qrAddress);
				Integer r2 = orderService.updateByPrimaryKeySelective(order);
				payMessage.setCode(Integer.parseInt("1"));
				payMessage.setMessage(Constents.SUCCESMESSAGE);
				payMessage.setOutTradeNo(payParams.getOutTradeNo());
				payMessage.setQrUrl(qrAddress);
				payMessage.setResultCode("SUCCESS");
				payMessage.setReturnCode("0");
				payMessage.setSign(payParams.getSign());
				payMessage.setReturnMsg((String) map.get("return_msg"));
				payMessage.setTradeType(trade_type);
			}
			if("SUCCESS".equals(returnCode) && "FAIL".equals(resultCode)) {
				String errCode = (String) map.get("err_code");
				if("ORDERCLOSED".equals(errCode)) {
					retMsg = "订单已关闭，请使用新的订单号发起交易。";
					// 冲新向微信发起支付请求
					newRequest = "YES";
				}
				if("NOAUTH".equals(errCode)) {
					retMsg = "商户未开通此接口权限，请商户前往申请此接口权限。";
				}
				if("NOTENOUGH".equals(errCode)) {
					retMsg = "用户帐号余额不足，请用户充值或更换支付卡后再支付。";
				}
				if("ORDERPAID".equals(errCode)) {
					retMsg = "此订单以完成支付，无需更多操作。";
				}
				if("SYSTEMERROR".equals(errCode)) {
					newRequest = "YES";
					retMsg = "微信系统异常，请用相同参数重新调用。";
				}
				if("APPID_NOT_EXIST".equals(errCode)) {
					retMsg = "APPID不存在，请检查APPID是否正确。";
				}
				if("MCHID_NOT_EXIST".equals(errCode)) {
					retMsg = "MCHID不存在，请检查MCHID是否正确。";
				}
				if("APPID_MCHID_NOT_MATCH".equals(errCode)) {
					retMsg = "请确认appid和mch_id是否匹配。";
				}
				if("LACK_PARAMS".equals(errCode)) {
					retMsg = "缺少必要的请求参数 ，请检查参数是否齐全 。";
				}
				if("OUT_TRADE_NO_USED".equals(errCode)) {
					retMsg = "请核实商户订单号是否重复提交。";
					newRequest = "YES";
				}
				if("SIGNERROR".equals(errCode)) {
					retMsg = "签名错误，请检查签名参数和方法是否都符合签名算法要求。";
				}
				if("POST_DATA_EMPTY".equals(errCode)) {
					retMsg = "请检查数据是否为空。";
				}
				if("XML_FORMAT_ERROR".equals(errCode) || "REQUIRE_POST_METHOD".equals(errCode)
				        || "NOT_UTF8".equals(errCode)) {
					retMsg = "系统出错，请联系支付系统管理员。";
					newRequest = "YES";
				}

				payMessage.setMessage(retMsg);
				payMessage.setOutTradeNo(payParams.getOutTradeNo());
				payMessage.setResultCode("FAIL");
				payMessage.setReturnCode("-1");
				payMessage.setSign(payParams.getSign());
				payMessage.setReturnMsg((String) map.get("return_msg"));
				payMessage.setTradeType(payParams.getTradeType());

			}

			retMap.put("retresXML", retresXML);
			retMap.put("newRequest", newRequest);
			retMap.put("payMessage", payMessage);

		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(resXml == null || "".equals(resXml)) {
				newRequest = "YES";
				retMap.put("retresXML", retresXML);
				retMap.put("newRequest", newRequest);
				retMap.put("payMessage", payMessage);
			}
		}
		
		return retMap;
	}
	
	public static String saveQr(String code_url,String nonStr) {
		String retStr = "";
		// 资源文件
		// code_url = "weixin://wxpay/bizpayurl?pr=dHP8OQA";
		try {
			int width = 200;
			int height = 200;
			String format = "png";
			Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
			BitMatrix bitMatrix = new MultiFormatWriter()
			        .encode(code_url, BarcodeFormat.QR_CODE, width, height, hints);
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			for(int x = 0;x < width;x++) {
				for(int y = 0;y < height;y++) {
					image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
				}
			}
			// String depth = "F:/codes";
			// String depth =
			// "E:/workspace1/git/springbootMrd/mrd-frame-web/src/main/webapp/qrimages";
			String depth = "C:/Users/AllisonWang/git/springbootMrd/mrd-frame-web/src/main/webapp/qrimages";
			mkdirs(depth);

			ImageIO.write(image, format, new File(depth + "/" +nonStr+ ".png"));
			// retStr = PayConfig.systemPublishPaht + "/qrimages" + "/" + nonStr + ".png";
			retStr = publishPath + "/qrimages" + "/" + nonStr + ".png";
			return retStr;

		} catch (WriterException e) {
			e.printStackTrace();

		} catch (IOException e) {
			e.printStackTrace();
		}
		return retStr;

	}

	public static void mkdirs(String destPath) {
		File file = new File(destPath);
		// 当文件夹不存在时，mkdirs会自动创建多层目录，区别于mkdir。(mkdir如果父目录不存在则会抛出异常)
		if(!file.exists() && !file.isDirectory()) {
			file.mkdirs();
		}
	}
}
